﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using RpgLibrary.SkillClasses;
using RpgLibrary.SpellClasses;
using RpgLibrary.TalentClasses;
using RpgLibrary.EffectClasses;

namespace RpgLibrary.CharacterClasses
{
    public enum EntityGender { Male, Female, Unknown }
    public enum EntityType { Character, NPC, Enemy, Creature }

    public sealed class Entity
    {
        //#region Skill Field and Property Region

        //readonly Dictionary<string, Skill> skills;
        //readonly List<Modifier> skillModifiers;
        
        //public Dictionary<string, Skill> Skills
        //{
        //    get { return skills; }
        //}

        //public List<Modifier> SkillModifiers
        //{
        //    get { return skillModifiers; }
        //}

        //#endregion
        
        //#region Spell Field and Property Region
        
        //readonly Dictionary<string, Spell> spells;
        //readonly List<Modifier> spellModifiers;
        
        //public Dictionary<string, Spell> Spells
        //{
        //    get { return spells; }
        //}

        //public List<Modifier> SpellModifiers
        //{
        //    get { return spellModifiers; }
        //}

        //#endregion
        
        //#region Talent Field and Property Region
        
        //readonly Dictionary<string, Talent> talents;
        //readonly List<Modifier> talentModifiers;
        //public Dictionary<string, Talent> Talents
        //{
        //    get { return talents; }
        //}

        //public List<Modifier> TalentModifiers
        //{
        //    get { return talentModifiers; }
        //}

        //#endregion

        //#region Resistance and Weakness Field and Property Region
        
        //private readonly List<Resistance> resistances;
        
        //public List<Resistance> Resistances
        //{
        //    get { return resistances; }
        //}
        
        //private readonly List<Weakness> weaknesses;
        
        //public List<Weakness> Weaknesses
        //{
        //    get { return weaknesses; }
        //}
        
        //#endregion

        #region Vital Field and Property Region

        private string entityName;
        private string entityClass;
        private EntityType entityType;
        private EntityGender gender;

        public string EntityName
        {
            get { return entityName; }
            set { entityName = value; }
        }

        public string EntityClass
        {
            get { return entityClass; }
            set { entityClass = value; }
        }

        public EntityType EntityType
        {
            get { return entityType; }
            set { entityType = value; }
        }

        public EntityGender Gender
        {
            get { return gender; }
            set { gender = value; }
        }

        #endregion
        
        #region Basic Attribute and Property Region
        
        private int strength;
        private int dexterity;
        private int cunning;
        private int willpower;
        private int magic;
        private int constitution;

        private int strengthModifier;
        private int dexterityModifier;
        private int cunningModifier;
        private int willpowerModifier;
        private int magicModifier;
        private int constitutionModifier;
        
        public int Strength
        {
            get { return strength + strengthModifier; }
            private set { strength = value; }
        }
        
        public int Dexterity
        {
            get { return dexterity + dexterityModifier; }
            private set { dexterity = value; }
        }
        
        public int Cunning
        {
            get { return cunning + cunningModifier; }
            private set { cunning = value; }
        }
        
        public int Willpower
        {
            get { return willpower + willpowerModifier; }
            private set { willpower = value; }
        }
        
        public int Magic
        {
            get { return magic + magicModifier; }
            private set { magic = value; }
        }
        
        public int Constitution
        {
            get { return constitution + constitutionModifier; }
            private set { constitution = value; }
        }
        
        #endregion
        
        #region Calculated Attribute Field and Property Region

        private AttributePair health;
        private AttributePair stamina;
        private AttributePair mana;
        
        public AttributePair Health
        {
            get { return health; }
        }
        
        public AttributePair Stamina
        {
            get { return stamina; }
        }
        
        public AttributePair Mana
        {
            get { return mana; }
        }

        private int attack;
        private int damage;
        private int defense;
        
        #endregion
        
        #region Level Field and Property Region

        private int level;
        private long experience;
        
        public int Level
        {
            get { return level; }
            private set { level = value; }
        }
        
        public long Experience
        {
            get { return experience; }
            private set { experience = value; }
        }
        
        #endregion
        
        #region Constructor Region
        
        private Entity()
        {
            Strength = 0;
            Dexterity = 0;
            Cunning = 0;
            Willpower = 0;
            Magic = 0;
            Constitution = 0;

            health = new AttributePair(0);
            stamina = new AttributePair(0);
            mana = new AttributePair(0);

            //skills = new Dictionary<string, Skill>();
            //spells = new Dictionary<string, Spell>();
            //talents = new Dictionary<string, Talent>();

            //skillModifiers = new List<Modifier>();
            //spellModifiers = new List<Modifier>();
            //talentModifiers = new List<Modifier>();

            //resistances = new List<Resistance>();
            //weaknesses = new List<Weakness>();
        }

        public Entity(EntityData entityData)
            : this()
        {
            EntityName = entityData.Name;
            EntityClass = entityData.EntityName;
            Gender = entityData.Gender;
            EntityType = entityData.EntityType;
            Strength = entityData.Strength;
            Dexterity = entityData.Dexterity;
            Cunning = entityData.Cunning;
            Willpower = entityData.Willpower;
            Magic = entityData.Magic;
            Constitution = entityData.Constitution;
            
            health = new AttributePair(0);
            stamina = new AttributePair(0);
            mana = new AttributePair(0);
        }
        #endregion

        #region Method Region

        //Hate hate hate. I really should make the attributes a collection
        public int GetAttributeByName(string attribute)
        {
            int value = -1;
            switch (attribute.ToLower())
            {
                case "strength":
                    value = this.Strength;
                    break;
                case "dexterity":
                    value = this.Dexterity;
                    break;
                case "cunning":
                    value = this.Cunning;
                    break;
                case "willpower":
                    value = this.Willpower;
                    break;
                case "magic":
                    value = this.Magic;
                    break;
                case "constitution":
                    value = this.Constitution;
                    break;
            }

            return value;
        }

        //public bool CanLearn(Talent talent)
        //{
        //    bool canLearn = true;

        //    if (this.Level < talent.LevelRequirement)
        //        canLearn = false;

        //    if (!talent.AllowedClasses.Contains(this.EntityClass.ToLower()))
        //        canLearn = false;

        //    foreach (string s in talent.AttributeRequirements.Keys)
        //    {
        //        if (this.GetAttributeByName(s) < talent.AttributeRequirements[s])
        //        {
        //            canLearn = false;
        //            break;
        //        }
        //    }

        //    foreach (string s in talent.TalentPrerequisites)
        //    {
        //        if (!this.Talents.ContainsKey(s))
        //        {
        //            canLearn = false;
        //            break;
        //        }
        //    }

        //    return canLearn;
        //}

        //public bool CanLearn(Spell spell)
        //{
        //    bool canLearn = true;

        //    if (this.Level < spell.LevelRequirement)
        //        canLearn = false;

        //    string entityClass = this.EntityClass.ToLower();

        //    if (!spell.AllowedClasses.Contains(entityClass))
        //        canLearn = false;

        //    foreach (string s in spell.AttributeRequirements.Keys)
        //    {
        //        if (this.GetAttributeByName(s) < spell.AttributeRequirements[s])
        //        {
        //            canLearn = false;
        //            break;
        //        }
        //    }

        //    foreach (string s in spell.SpellPrerequisites)
        //    {
        //        if (!this.Spells.ContainsKey(s))
        //        {
        //            canLearn = false;
        //            break;
        //        }
        //    }

        //    return canLearn;
        //}

        public bool IsClass(string className)
        {
            return entityClass == className;
        }

        public void Update(TimeSpan elapsedTime)
        {
            //foreach (Modifier modifier in skillModifiers)
            //    modifier.Update(elapsedTime);

            //foreach (Modifier modifier in spellModifiers)
            //    modifier.Update(elapsedTime);
            
            //foreach (Modifier modifier in talentModifiers)
            //    modifier.Update(elapsedTime);
        }
        #endregion

        internal static Entity FromEntityData(EntityData entityData)
        {
            return new Entity(entityData);
        }

        internal EntityData GetDataObject()
        {
            return new EntityData(
                this.EntityName,
                this.Strength,
                this.Dexterity,
                this.Cunning,
                this.Willpower,
                this.Magic,
                this.Constitution,
                string.Empty,
                string.Empty,
                string.Empty);
        }
    }
}